import Clipboard from 'clipboard'
import axios from 'axios'
import { translate } from '@/utils/i18n'

export function debounce(func, wait) {
  let timeout;
  return function(...args) {
    const context = this;
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      func.apply(context, args);
    }, wait);
  };
}

export function isNull(value) {
  return value === null || value === undefined
}

export function isNotNull(value) {
  return value !== null && value !== undefined
}

export function isEmptyStr(str) {
  //return (str === undefined) || (!str) || (!/[^\s]/.test(str));
  return (
    str === undefined ||
    (!str && str !== 0 && str !== '0') ||
    !/[^\s]/.test(str)
  )
}

/**
 * 判断是否是json字符串
 */
export function isJSON(str) {
  try {
    JSON.parse(str);
  } catch (e) {
    return false;
  }
  return true;
}

export const generateId = function () {
  return Math.floor(
    Math.random() * 100000 + Math.random() * 20000 + Math.random() * 5000
  )
}

export const deepClone = function (origin) {
  if (origin === undefined) {
    return undefined
  }

  return JSON.parse(JSON.stringify(origin))
}

export const overwriteObj = function (obj1, obj2) {
  /* 浅拷贝对象属性，obj2覆盖obj1 */
  Object.keys(obj2).forEach((prop) => {
    obj1[prop] = obj2[prop]
  })
}

/**
 * 用Function对象实现eval函数功能
 * @param fn 函数体代码
 * @param DSV DSV变量
 * @param VFR 表单组件
 * @param formulaJs formula-js对象
 * @returns {*}
 */
export const evalFn = function (fn, DSV = null, VFR = null, formulaJs = null) {
  let f = new Function('DSV', 'VFR', 'LS', 'formulaJs', 'return ' + fn)
  return f(DSV, VFR, localStorage, formulaJs)
}

export const trimEx = function (str, char, type) {
  if (char) {
    if (type === 'left') {
      return str.replace(new RegExp('^\\' + char + '+', 'g'), '')
    } else if (type === 'right') {
      return str.replace(new RegExp('\\' + char + '+$', 'g'), '')
    }

    return str.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), '')
  }

  return str.replace(/^\s+|\s+$/g, '')
}

export const hasPropertyOfObject = function (obj, propPath) {
  const keys = propPath.split('.')
  let tmpObj = obj
  let result = true

  for (const key of keys) {
    if (!tmpObj.hasOwnProperty(key)) {
      result = false
      break
    } else {
      tmpObj = tmpObj[key]
    }
  }

  return result
}

export const objectKeysToArray = function (obj) {
  if (!obj) return []

  const resultArray = []
  Object.keys(obj).forEach((key) => {
    console.log(obj[key][0].message)
    // 1、抛出唯一id用：key；2、抛出用户提示用message；
    const message = obj[key][0].message
    resultArray.push(message)
  })

  return resultArray
}

function isDef(value) {
  return value !== undefined && value !== null
}

export const getObjectValue = function (obj, propPath) {
  const keys = propPath.split('.')
  let result = obj

  keys.forEach((key) => {
    result = isDef(result) && isDef(result[key]) ? result[key] : null
  })

  return result
}

export const setObjectValue = function (obj, objectName, value) {
  const objectChains = objectName.split('.')
  let objectModel = obj

  objectChains.forEach((key, idx) => {
    if (!key) return

    if (idx === objectChains.length - 1) {
      objectModel[key] = value
      return
    }

    if (objectModel[key] === undefined) {
      objectModel[key] = {}
    }
    objectModel = objectModel[key]
  })
}

export const addWindowResizeHandler = function (handler) {
  let oldHandler = window.onresize
  if (typeof window.onresize != 'function') {
    window.onresize = handler
  } else {
    window.onresize = function () {
      oldHandler()
      handler()
    }
  }
}

const createStyleSheet = function () {
  let head = document.head || document.getElementsByTagName('head')[0]
  let style = document.createElement('style')
  style.type = 'text/css'
  head.appendChild(style)
  return style.sheet
}

export const insertCustomCssToHead = function (cssCode, formId = '') {
  const head = document.getElementsByTagName('head')[0]
  let oldStyle = document.getElementById('vform-custom-css')
  if (!!oldStyle) {
    head.removeChild(oldStyle) //先清除后插入！！
  }
  if (!!formId) {
    oldStyle = document.getElementById('vform-custom-css' + '-' + formId)
    !!oldStyle && head.removeChild(oldStyle) //先清除后插入！！
  }

  let newStyle = document.createElement('style')
  newStyle.type = 'text/css'
  newStyle.rel = 'stylesheet'
  newStyle.id = !!formId
    ? 'vform-custom-css' + '-' + formId
    : 'vform-custom-css'
  try {
    newStyle.appendChild(document.createTextNode(cssCode))
  } catch (ex) {
    newStyle.styleSheet.cssText = cssCode
  }

  head.appendChild(newStyle)
}

export const insertGlobalFunctionsToHtml = function (
  functionsCode,
  formId = ''
) {
  const bodyEle = document.getElementsByTagName('body')[0]
  let oldScriptEle = document.getElementById('v_form_global_functions')
  !!oldScriptEle && bodyEle.removeChild(oldScriptEle) //先清除后插入！！
  if (!!formId) {
    oldScriptEle = document.getElementById(
      'v_form_global_functions' + '-' + formId
    )
    !!oldScriptEle && bodyEle.removeChild(oldScriptEle) //先清除后插入！！
  }

  let newScriptEle = document.createElement('script')
  newScriptEle.id = !!formId
    ? 'v_form_global_functions' + '-' + formId
    : 'v_form_global_functions'
  newScriptEle.type = 'text/javascript'
  newScriptEle.innerHTML = functionsCode
  bodyEle.appendChild(newScriptEle)
}

export const deleteCustomStyleAndScriptNode = function (previewState, formId) {
  const head = document.getElementsByTagName('head')[0]
  let oldStyle = document.getElementById('vform-custom-css' + '-' + formId)
  if (previewState) {
    oldStyle = document.getElementById('vform-custom-css')
  }
  if (!!oldStyle) {
    head.removeChild(oldStyle)
  }

  const bodyEle = document.getElementsByTagName('body')[0]
  let oldScriptEle = document.getElementById(
    'v_form_global_functions' + '-' + formId
  )
  if (previewState) {
    oldScriptEle = document.getElementById('v_form_global_functions')
  }
  if (!!oldScriptEle) {
    bodyEle.removeChild(oldScriptEle)
  }
}

export const optionExists = function (optionsObj, optionName) {
  if (!optionsObj) {
    return false
  }

  return Object.keys(optionsObj).indexOf(optionName) > -1
}

export const loadRemoteScript = function (srcPath, callback) {
  /*加载远程js，加载成功后执行回调函数*/
  let sid = encodeURIComponent(srcPath)
  let oldScriptEle = document.getElementById(sid)

  if (!oldScriptEle) {
    let s = document.createElement('script')
    s.src = srcPath
    s.id = sid
    document.body.appendChild(s)

    s.onload = s.onreadystatechange = function (_, isAbort) {
      /* 借鉴自ace.js */
      if (
        isAbort ||
        !s.readyState ||
        s.readyState === 'loaded' ||
        s.readyState === 'complete'
      ) {
        s = s.onload = s.onreadystatechange = null
        if (!isAbort) {
          callback()
        }
      }
    }
  }
}

export function traverseFieldWidgets(widgetList, handler, parent = null, staticWidgetsIncluded = false, 
  skipSubFormContainer = false, skipObjectGroupContainer = false) {

  if (!widgetList) {
    return
  }

  widgetList.map((w) => {
    if (w.formItemFlag || (w.formItemFlag === false && staticWidgetsIncluded)) {
      handler(w, parent)
    } else if (w.type === 'grid') {
      w.cols.map((col) => {
        traverseFieldWidgets(col.widgetList, handler, w, staticWidgetsIncluded)
      })
    } else if (w.type === 'left-right') {
      w.cols.map((col) => {
        traverseFieldWidgets(col.widgetList, handler, w, staticWidgetsIncluded)
      })
    } else if (w.type === 'table') {
      w.rows.map((row) => {
        row.cols.map((cell) => {
          traverseFieldWidgets(
            cell.widgetList,
            handler,
            w,
            staticWidgetsIncluded
          )
        })
      })
    } else if (w.type === 'tab') {
      w.tabs.map((tab) => {
        traverseFieldWidgets(tab.widgetList, handler, w, staticWidgetsIncluded)
      })
    } else if (widgetIsSubFormType(w)) {
      if (!skipSubFormContainer) {
        const arr = w.widgetFooterList?.length ? [...w.widgetList, ...w.widgetFooterList] : w.widgetList;
        traverseFieldWidgets(arr, handler, w, staticWidgetsIncluded)
      }
    } else if (w.category === 'container') { //自定义容器
      if (!skipObjectGroupContainer || (w.type !== 'object-group')) {
        traverseFieldWidgets(w.widgetList, handler, w, staticWidgetsIncluded)
      }
    }
  })
}

export function traverseContainerWidgets(widgetList, handler, skipDialogAndDrawer) {
  if (!widgetList) {
    return
  }

  widgetList.map((w) => {
    if (w.category === 'container') {
      if (skipDialogAndDrawer && ((w.type === 'vf-dialog') || (w.type === 'vf-drawer'))) {
        //什么也不做
      } else {
        handler(w)
      }
    }
    if (w.type === 'grid') {
      w.cols.map((col) => {
        traverseContainerWidgets(col.widgetList, handler)
      })
    } else if (w.type === 'table') {
      w.rows.map((row) => {
        row.cols.map((cell) => {
          traverseContainerWidgets(cell.widgetList, handler)
        })
      })
    } else if (w.type === 'left-right') {
      w.cols.map((col) => {
        traverseContainerWidgets(col.widgetList, handler)
      })
    } else if (w.type === 'tab') {
      w.tabs.map((tab) => {
        traverseContainerWidgets(tab.widgetList, handler)
      })
    } else if (widgetIsSubFormType(w)) {
      traverseContainerWidgets(w.widgetList, handler)
    } else if (w.category === 'container') {  //自定义容器
      if (skipDialogAndDrawer && ((w.type === 'vf-dialog') || (w.type === 'vf-drawer'))) {
        //什么也不做
      } else {
        traverseContainerWidgets(w.widgetList, handler)
      }
    }
  })
}

export function traverseAllWidgets(widgetList, handler) {
  if (!widgetList) {
    return
  }

  widgetList.map((w) => {
    handler(w)

    if (w.type === 'grid') {
      w.cols.map((col) => {
        handler(col)
        traverseAllWidgets(col.widgetList, handler)
      })
    } else if (w.type === 'table') {
      w.rows.map((row) => {
        row.cols.map((cell) => {
          handler(cell)
          traverseAllWidgets(cell.widgetList, handler)
        })
      })
    } else if (w.type === 'tab') {
      w.tabs.map((tab) => {
        traverseAllWidgets(tab.widgetList, handler)
      })
    } else if (widgetIsSubFormType(w)) {
      traverseAllWidgets(w.widgetList, handler)
    } else if (w.category === 'container') {
      //自定义容器
      traverseAllWidgets(w.widgetList, handler)
    }
  })
}

function handleWidgetForTraverse(widget, handler, staticWidgetsIncluded = false) {
  if (!!widget.category && widget.category === 'container') {
    traverseFieldWidgetsOfContainer(widget, handler)
  } else if (widget.formItemFlag || staticWidgetsIncluded) {
    handler(widget)
  }
}

/**
 * 遍历容器内的字段组件
 * @param con
 * @param handler
 * @param staticWidgetsIncluded
 */
export function traverseFieldWidgetsOfContainer(con, handler, staticWidgetsIncluded = false) {
  if (con.type === 'grid') {
    con.cols.forEach(col => {
      col.widgetList.forEach(cw => {
        handleWidgetForTraverse(cw, handler, staticWidgetsIncluded)
      })
    })
  } else if (con.type === 'table') {
    con.rows.forEach(row => {
      row.cols.forEach(cell => {
        cell.widgetList.forEach(cw => {
          handleWidgetForTraverse(cw, handler, staticWidgetsIncluded)
        })
      })
    })
  } else if (con.type === 'tab') {
    con.tabs.forEach(tab => {
      tab.widgetList.forEach(cw => {
        handleWidgetForTraverse(cw, handler, staticWidgetsIncluded)
      })
    })
  } else if (widgetIsSubFormType(con)) {
    // 处理兼容表尾
    const arr = con.widgetFooterList?.length ? [...con.widgetList, ...con.widgetFooterList] : con.widgetList;
    arr.forEach(cw => {
      handleWidgetForTraverse(cw, handler, staticWidgetsIncluded)
    })
  } else if (con.category === 'container') {  //自定义容器
    con.widgetList.forEach(cw => {
      handleWidgetForTraverse(cw, handler, staticWidgetsIncluded)
    })
  }
}

function handleContainerTraverse(
  widget,
  fieldHandler,
  containerHandler,
  internalContainerCallFlag,
  staticWidgetsIncluded
) {
  if (!!widget.category && widget.category === 'container') {
    traverseWidgetsOfContainer(
      widget,
      fieldHandler,
      containerHandler,
      internalContainerCallFlag,
      staticWidgetsIncluded
    )
  } else if (widget.formItemFlag) {
    fieldHandler(widget)
  } else if (staticWidgetsIncluded) {
    fieldHandler(widget)
  }
}

/**
 * 遍历容器内部的字段组件和容器组件
 * @param con
 * @param fieldHandler
 * @param containerHandler
 * @param internalContainerCallFlag 是否需要处理内部容器组件，默认不处理
 * @param staticWidgetsIncluded 是否需要处理静态非表单交互类组件
 */
export function traverseWidgetsOfContainer(
  con,
  fieldHandler,
  containerHandler,
  internalContainerCallFlag,
  staticWidgetsIncluded
) {
  if (con.category === 'container') {
    containerHandler(con)
  }

  if (con.type === 'grid' || con.type === 'left-right') {
    con.cols.forEach((col) => {
      if (internalContainerCallFlag) {
        containerHandler(col)
      }
      col.widgetList.forEach((cw) => {
        handleContainerTraverse(
          cw,
          fieldHandler,
          containerHandler,
          internalContainerCallFlag,
          staticWidgetsIncluded
        )
      })
    })
  } else if (con.type === 'table') {
    con.rows.forEach((row) => {
      if (internalContainerCallFlag) {
        containerHandler(row)
      }
      row.cols.forEach((cell) => {
        if (internalContainerCallFlag) {
          containerHandler(cell)
        }
        cell.widgetList.forEach((cw) => {
          handleContainerTraverse(
            cw,
            fieldHandler,
            containerHandler,
            internalContainerCallFlag,
            staticWidgetsIncluded
          )
        })
      })
    })
  } else if (con.type === 'tab') {
    con.tabs.forEach((tab) => {
      if (internalContainerCallFlag) {
        containerHandler(tab)
      }
      tab.widgetList.forEach((cw) => {
        handleContainerTraverse(
          cw,
          fieldHandler,
          containerHandler,
          internalContainerCallFlag,
          staticWidgetsIncluded
        )
      })
    })
  } else if (widgetIsSubFormType(con)) {
    con.widgetList.forEach((cw) => {
      handleContainerTraverse(
        cw,
        fieldHandler,
        containerHandler,
        internalContainerCallFlag,
        staticWidgetsIncluded
      )
    })
  } else if (con.category === 'container') {
    //自定义容器
    con.widgetList.forEach((cw) => {
      handleContainerTraverse(
        cw,
        fieldHandler,
        containerHandler,
        internalContainerCallFlag,
        staticWidgetsIncluded
      )
    })
  }
}

export function traverseWidgetsOfGridCol(
  gridCol,
  fieldHandler,
  containerHandler
) {
  // if (gridCol.category === 'container') {
  //   containerHandler(gridCol)
  // }

  if (gridCol.type === 'grid-col') {
    gridCol.widgetList.forEach((cw) => {
      handleContainerTraverse(cw, fieldHandler, containerHandler)
    })
  }
}

/**
 * 获取所有字段组件
 * @param widgetList
 * @param staticWidgetsIncluded 是否包含按钮等静态组件，默认不包含
 * @param skipSubFormContainer 是否跳过子表单容器
 * @param skipObjectGroupContainer  是否跳过对象容器
 * @returns {[]}
 */
export function getAllFieldWidgets(widgetList, staticWidgetsIncluded = false,
  skipSubFormContainer = false, skipObjectGroupContainer = false) {
  if (!widgetList) {
  return []
  }

  let result = []
  let handlerFn = (w) => {
  result.push({
  type: w.type,
  name: w.options.name,
  field: w
  })
  }
  traverseFieldWidgets(widgetList, handlerFn, null, staticWidgetsIncluded, skipSubFormContainer, skipObjectGroupContainer)

  return result
}

/**
 * 获取所有容器组件
 * @param widgetList
 * @param skipDialogAndDrawer 是否跳过弹窗和抽屉内部组件，默认不跳过
 * @returns {[]}
 */
export function getAllContainerWidgets(widgetList, skipDialogAndDrawer) {
  if (!widgetList) {
    return []
  }

  let result = []
  let handlerFn = (w) => {
    result.push({
      type: w.type,
      name: w.options.name,
      container: w,
    })
  }
  traverseContainerWidgets(widgetList, handlerFn, skipDialogAndDrawer)

  return result
}

export function getFieldWidgetByName(
  widgetList,
  fieldName,
  staticWidgetsIncluded
) {
  if (!widgetList) {
    return null
  }

  let foundWidget = null
  let handlerFn = (widget) => {
    if (widget.options.name === fieldName) {
      foundWidget = widget
    }
  }

  traverseFieldWidgets(widgetList, handlerFn, null, staticWidgetsIncluded)
  return foundWidget
}

export function getFieldWidgetById(widgetList, fieldId, staticWidgetsIncluded) {
  if (!widgetList) {
    return null
  }

  let foundWidget = null
  let handlerFn = (widget) => {
    if (widget.id === fieldId) {
      foundWidget = widget
    }
  }

  traverseFieldWidgets(widgetList, handlerFn, null, staticWidgetsIncluded)
  return foundWidget
}

export function getSubFormNameByFieldId(widgetList, fieldId) {
  let subFormName = null
  const allCons = getAllContainerWidgets(widgetList)
  allCons.forEach((cw) => {
    const fwHandler = (fw) => {
      if (fw.id === fieldId) {
        subFormName = cw.name
      }
    }

    if (widgetIsSubFormType(cw)) {
      traverseFieldWidgetsOfContainer(cw.container, fwHandler)
    }
  })

  return subFormName
}

export function getContainerWidgetByName(widgetList, containerName) {
  if (!widgetList) {
    return null
  }

  let foundContainer = null
  let handlerFn = (con) => {
    if (con.options.name === containerName) {
      foundContainer = con
    }
  }

  traverseContainerWidgets(widgetList, handlerFn)
  return foundContainer
}

export function getContainerWidgetById(widgetList, containerId) {
  if (!widgetList) {
    return null
  }

  let foundContainer = null
  let handlerFn = (con) => {
    if (con.id === containerId) {
      foundContainer = con
    }
  }

  traverseContainerWidgets(widgetList, handlerFn)
  return foundContainer
}

export function copyToClipboard(
  content,
  clickEvent,
  $message,
  successMsg,
  errorMsg
) {
  const clipboard = new Clipboard(clickEvent.target, {
    text: () => content,
  })

  clipboard.on('success', () => {
    $message.success(successMsg)
    clipboard.destroy()
  })

  clipboard.on('error', () => {
    $message.error(errorMsg)
    clipboard.destroy()
  })

  clipboard.onClick(clickEvent)
}

export function getQueryParam(variable) {
  let query = window.location.search.substring(1)
  let vars = query.split('&')
  for (let i = 0; i < vars.length; i++) {
    let pair = vars[i].split('=')
    if (pair[0] == variable) {
      return pair[1]
    }
  }

  return undefined
}

export function getDefaultFormConfig() {
  return {
    modelName: 'formData',
    refName: 'vForm',
    rulesName: 'rules',
    labelWidth: 80,
    labelPosition: 'left',
    h5LabelTop: true,  //H5布局，标签是否强制显示在顶部
    gridResponsive: true,  //栅格是否自动开启响应式
    size: '',
    labelAlign: 'label-left-align',
    cssCode: '',
    customClass: [],
    functions: '',  //全局函数
    layoutType: 'PC',
    jsonVersion: 3,
    dataSources: [],  //数据源集合

    onFormCreated: '',
    onFormMounted: '',
    onFormDataChange: '',
    onFormValidate: '',
  }
}

export function buildDefaultFormJson() {
  return {
    widgetList: [],
    widgetViewList: [],
    formConfig: deepClone(getDefaultFormConfig()),
  }
}

export function cloneFormConfigWithoutEventHandler(formConfig) {
  let newFC = deepClone(formConfig)
  newFC.onFormCreated = ''
  newFC.onFormMounted = ''
  newFC.onFormDataChange = ''
  newFC.onFormValidate = ''

  return newFC
}

/**
 * 转译选择项数据
 * @param rawData
 * @param widgetType
 * @param labelKey
 * @param valueKey
 * @returns {[]}
 */
export function translateOptionItems(rawData, widgetType, labelKey, valueKey) {
  if (widgetType === 'cascader') {
    // 级联选择不转译
    return deepClone(rawData)
  }

  let result = []
  if (!!rawData && rawData.length > 0) {
    rawData.forEach((ri) => {
      if (ri.hasOwnProperty('disabled')) {
        result.push({
          label: ri[labelKey],
          value: ri[valueKey],
          disabled: ri['disabled'],
        })
      } else {
        result.push({
          label: ri[labelKey],
          value: ri[valueKey],
        })
      }
    })
  }

  return result
}

/**
 * 组装axios请求配置参数
 * @param arrayObj
 * @param DSV
 * @param VFR
 * @returns {{}}
 */
export function assembleAxiosConfig(arrayObj, DSV, VFR) {
  let result = {}
  if (!arrayObj || arrayObj.length <= 0) {
    return result
  }

  arrayObj.map((ai) => {
    if (ai.type === 'String') {
      result[ai.name] = String(ai.value)
    } else if (ai.type === 'Number') {
      result[ai.name] = Number(ai.value)
    } else if (ai.type === 'Boolean') {
      if (ai.value.toLowerCase() === 'false' || ai.value === '0') {
        result[ai.name] = false
      } else if (ai.value.toLowerCase() === 'true' || ai.value === '1') {
        result[ai.name] = true
      } else {
        result[ai.name] = null
      }
    } else if (ai.type === 'Variable') {
      result[ai.name] = evalFn(ai.value, DSV, VFR)
    }
  })

  /* 加入如下两行日志打印代码，是为了防止编译打包时DSV、VFR参数被剔除！！ begin */
  /* DSV、VFR入参没有在本函数中直接使用到，但在eval表达式中可能被使用到，故需确保DSV、VFR参数始终存在！！ */
  console.log('test DSV: ', DSV)
  console.log('test VFR: ', VFR)
  /* 加入如下两行日志打印代码，是为了防止编译打包时DSV、VFR入参会被剔除！！ end */

  return result
}

function buildRequestConfig(dataSource, DSV, VFR, isSandbox) {
  let config = {}
  if (dataSource.requestURLType === 'String') {
    config.url = dataSource.requestURL
  } else {
    config.url = evalFn(dataSource.requestURL, DSV, VFR)
  }
  config.method = dataSource.requestMethod

  config.headers = assembleAxiosConfig(dataSource.headers, DSV, VFR)
  config.params = assembleAxiosConfig(dataSource.params, DSV, VFR)
  config.data = assembleAxiosConfig(dataSource.data, DSV, VFR)

  let chFn = new Function(
    'config',
    'isSandbox',
    'DSV',
    'VFR',
    dataSource.configHandlerCode
  )
  return chFn.call(null, config, isSandbox, DSV, VFR)
}

export async function runDataSourceRequest(
  dataSource,
  DSV,
  VFR,
  isSandbox,
  $message
) {
  try {
    let requestConfig = buildRequestConfig(dataSource, DSV, VFR, isSandbox)
    //console.log('test------', requestConfig)
    let result = await axios.request(requestConfig)
    //let result = await axios.create().request(requestConfig)

    let dhFn = new Function(
      'result',
      'isSandbox',
      'DSV',
      'VFR',
      dataSource.dataHandlerCode
    )
    return dhFn.call(null, result, isSandbox, DSV, VFR)
  } catch (err) {
    let ehFn = new Function(
      'error',
      'isSandbox',
      'DSV',
      '$message',
      'VFR',
      dataSource.errorHandlerCode
    )
    console.error(err)
    return ehFn.call(null, err, isSandbox, DSV, $message, VFR)
  }
}

export function getDSByName(formConfig, dsName) {
  let resultDS = null
  if (!!dsName && !!formConfig.dataSources) {
    formConfig.dataSources.forEach((ds) => {
      if (ds.uniqueName === dsName) {
        resultDS = ds
      }
    })
  }

  if (!resultDS) {
    console.error('DS not found: ' + dsName)
  }

  return resultDS
}

export function getVantWidget(mixModeFlag, widgetType) {
  if (!mixModeFlag)
    return widgetType

  let vwMap = {
    'select': 'vant-select',
    'date': 'vant-date',
    'date-range': 'vant-date-range',
    'time': 'vant-time',
    'time-range': 'vant-time-range',
    'cascader': 'vant-cascader',
  }
  return vwMap[widgetType] || widgetType
}

//扩展：数字转千分位
export function formatMillennials(number){
  return number.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

export function widgetIsSubFormType(w) {
  return w.type === 'sub-form' || w.type === 'grid-sub-form' || w.type === "table-sub-form"
}

/**********************  以下是自定义方法  **********************/

/**
 * 数组对象去重
 */
export function uniqueByProperty(arr, prop) {
  if (arr.length === 1) {
    return arr
  } else if (arr.length > 0) {
    let map = new Map()
    for (let i = 0; i < arr.length; i++) {
      if (!map.has(arr[i][prop])) {
        map.set(arr[i][prop])
        i--
      } else {
        arr.splice(i, 1)
      }
    }
    return arr
  }
}

export class SetDomStyle {
  styleObj = {}
  constructor(dom, config) {
    this.dom = dom
    this.config = config
    this.getFormItemStyle(config, true)
  }

  /**
   * 获取表单项样式
   *
   * @param config 表单项配置
   * @param isInit 是否为初始化状态
   * @returns 返回包含样式的对象
   */
  getFormItemStyle(config, isInit) {
    if (!(config instanceof Object)) return
    let isDetailTable = config && config.detailSubTable // 为了适配明细表组件
    let labelPositionConfig = config.labelPositionConfig || {}
    let contentPositionConfig = config.contentPositionConfig || {}
    let labelBorderConfig = config.labelBorderConfig || {}
    let contentBorderConfig = config.contentBorderConfig || {}
    let formItemBorderConfig = config.formItemBorderConfig || {}
    let labelTextAlignLineHeight = config.height || (!config.alignColumn ? config.minHeight : '')
    let variableObj = {
      border: this.getBorderConfig(
        formItemBorderConfig.borderAllConfig,
        isDetailTable
      ),
      'border-top': this.getBorderConfig(formItemBorderConfig.borderTopConfig),
      'border-right': this.getBorderConfig(
        formItemBorderConfig.borderRightConfig
      ),
      'border-bottom': this.getBorderConfig(
        formItemBorderConfig.borderBottomConfig
      ),
      'border-left': this.getBorderConfig(
        formItemBorderConfig.borderLeftConfig
      ),
      '--form-item-textarea-lineHigh-variable': config.lineHeight
        ? config.lineHeight + 'px'
        : undefined,
      '--form-item-align-variable': config.alignColumn ? 'column' : 'row',
      '--form-item-left-padding-variable': config.alignColumn ? '0px' : '15px',
      '--font-color-variable': config.fontColor, // 字体颜色
      '--font-size-variable': config.fontSize
        ? config.fontSize + 'px'
        : undefined,
      '--font-family-variable': config.fontFamily,
      '--font-align-variable': config.labelPositionOfColumn,
      '--font-align-row-variable': config.labelPositionOfRow,
      '--label-justify-content-variable': config.labelTextAlign
        ? 'justify'
        : config.labelWhiteSpace ? config.labelPositionOfRow : config.labelPosition,
      '--item-height-variable': config.height
        ? config.height + 'px'
        : isInit
          ? '100%'
          : undefined,
      '--label-height--variable': config.labelHeight
        ? config.labelHeight + 'px'
        : isInit
          ? 'initial'
          : undefined,
      '--item-min-height-variable': config.minHeight
        ? config.minHeight + 'px'
        : undefined,
      '--content-align-variable': config.contentPositionOfColumn,
      '--content-vertical-align-variable': config.contentPositionOfAlign,
      '--label-background-color-variable': config.labelBackgroundColor,
      '--content-background-color-variable': config.contentBackgroundColor,
      '--content-font-family-variable': config.ContentFontFamily,
      '--content-font-color-variable': config.ContentFontColor,
      '--content-font-size-variable': config.contentFontSize
        ? config.contentFontSize + 'px'
        : undefined,
      '--label-width-space-variable': config.labelSpace
        ? config.labelSpace + 'px'
        : undefined,
      '--label-width-variable': config.labelWidth
        ? config.labelWidth + 'px'
        : isInit,
      '--label-margin-top-variable': labelPositionConfig.marginTop
        ? labelPositionConfig.marginTop + 'px'
        : isInit,
      '--label-margin-right-variable': labelPositionConfig.marginRight
        ? labelPositionConfig.marginRight + 'px'
        : isInit,
      '--label-margin-bottom-variable': labelPositionConfig.marginBottom
        ? labelPositionConfig.marginBottom + 'px'
        : isInit,
      '--label-margin-left-variable': labelPositionConfig.marginLeft
        ? labelPositionConfig.marginLeft + 'px'
        : isInit,
      '--label-padding-top-variable': labelPositionConfig.paddingTop
        ? labelPositionConfig.paddingTop + 'px'
        : isDetailTable
          ? '6px'
          : isInit,
      '--label-padding-right-variable': labelPositionConfig.paddingRight
        ? labelPositionConfig.paddingRight + 'px'
        : isDetailTable
          ? '10px'
          : isInit,
      '--label-padding-bottom-variable': labelPositionConfig.paddingBottom
        ? labelPositionConfig.paddingBottom + 'px'
        : isDetailTable
          ? '6px'
          : isInit,
      '--label-padding-left-variable': labelPositionConfig.paddingLeft
        ? labelPositionConfig.paddingLeft + 'px'
        : isDetailTable
          ? '10px'
          : isInit,
      '--label-border-variable': this.getBorderConfig(
        labelBorderConfig.borderAllConfig,
        isDetailTable
      ),
      '--label-border-top-variable': this.getBorderConfig(
        labelBorderConfig.borderTopConfig,
        isDetailTable
      ),
      '--label-border-right-variable': this.getBorderConfig(
        labelBorderConfig.borderRightConfig,
        isDetailTable
      ),
      '--label-border-bottom-variable': this.getBorderConfig(
        labelBorderConfig.borderBottomConfig,
        isDetailTable
      ),
      '--label-border-left-variable': this.getBorderConfig(
        labelBorderConfig.borderLeftConfig,
        isDetailTable
      ),
      '--content-border-variable': this.getBorderConfig(
        contentBorderConfig.borderAllConfig,
        isDetailTable
      ),
      '--content-border-top-variable': this.getBorderConfig(
        contentBorderConfig.borderTopConfig,
        isDetailTable
      ),
      '--content-border-right-variable': this.getBorderConfig(
        contentBorderConfig.borderRightConfig,
        isDetailTable
      ),
      '--content-border-bottom-variable': this.getBorderConfig(
        contentBorderConfig.borderBottomConfig,
        isDetailTable
      ),
      '--content-border-left-variable': this.getBorderConfig(
        contentBorderConfig.borderLeftConfig,
        isDetailTable
      ),
      '--content-margin-top-variable': contentPositionConfig.marginTop
        ? contentPositionConfig.marginTop + 'px'
        : isInit,
      '--content-margin-right-variable': contentPositionConfig.marginRight
        ? contentPositionConfig.marginRight + 'px'
        : isInit,
      '--content-margin-bottom-variable': contentPositionConfig.marginBottom
        ? contentPositionConfig.marginBottom + 'px'
        : isInit,
      '--content-margin-left-variable': contentPositionConfig.marginLeft
        ? contentPositionConfig.marginLeft + 'px'
        : isInit,
      '--content-padding-top-variable': contentPositionConfig.paddingTop
        ? contentPositionConfig.paddingTop + 'px'
        : isDetailTable
          ? '6px'
          : isInit,
      '--content-padding-right-variable': contentPositionConfig.paddingRight
        ? contentPositionConfig.paddingRight + 'px'
        : isDetailTable
          ? '10px'
          : isInit,
      '--content-padding-bottom-variable': contentPositionConfig.paddingBottom
        ? contentPositionConfig.paddingBottom + 'px'
        : isDetailTable
          ? '6px'
          : isInit,
      '--content-padding-left-variable': contentPositionConfig.paddingLeft
        ? contentPositionConfig.paddingLeft + 'px'
        : isDetailTable
          ? '10px'
          : isInit,
      '--label-has-colon-variable': config.hasColon ? 'block' : 'none',
      '--label-colon-top-variable': config.labelPositionOfColumn == 'flex-start' ? '0' : config.labelPositionOfColumn == 'center' ? '50%' : '100%',
      '--label-text-align-last': config.labelTextAlign ? 'justify' : '',
      // '--label-text-align-display': config.labelTextAlign ? 'block' : 'flex',
      // '--label-text-align-padding': config.labelTextAlign ? '10px' : '',
      '--label-text-span-width': config.labelTextAlign ? '100%' : 'initial',
      '--label-text-align-lineHeight': config.labelTextAlign && config.labelPositionOfColumn == 'center' ? (labelTextAlignLineHeight && (labelTextAlignLineHeight + 'px')) : undefined,
      '--label-min-height': !config.alignColumn && config.minHeight ? config.minHeight + 'px' : '',
      '--label-white-space': config.labelWhiteSpace ? 'pre-line' : 'nowrap',
      '--append-padding': config.appendPadding ? config.appendPadding + 'px' : '',
      '--apend-back-color': config.appendBackColor,
      'padding': config.alignColumn ? '0px !important' : '',
      '--label-line-height': config.labelLineHeight ? config.labelLineHeight: '',
      '--content-line-height': config.contentLineHeight ? config.contentLineHeight : '',
    }
    for (const key in variableObj) {
      if (!variableObj[key]) {
        delete variableObj[key]
      }
    }
    this.styleObj = variableObj
    return variableObj
  }

  setStyle() {
    var siblings = this.dom.children
    var itemSibling = null
    for (var i = 0; i < siblings.length; i++) {
      // if (this.dom.classList.contains("container-wrapper")) {
      //   //容器组件
      //   if (siblings[i].classList.contains("table-cell")) {
      //     itemSibling = siblings[i];
      //     break; // 找到后退出循环
      //   }
      // }
      if (this.dom.classList.contains('table-cell')) {
        itemSibling = this.dom
      } else if (this.dom.classList.contains('field-wrapper')) {
        //字段组件
        if (
          siblings[i].classList.contains('el-form-item') ||
          siblings[i].classList.contains('static-content-item')
        ) {
          itemSibling = siblings[i]
          break // 找到后退出循环
        }
      }
    }
    if (itemSibling) {
      // 遍历对象的每个键值对
      const stylePairs = Object.entries(this.styleObj).map(([key, value]) => {
        // 自定义属性需要以 `var(--variable-name)` 的形式引用
        return `${key}: ${value}`
      })
      // 将键值对数组转换为由分号分隔的字符串
      const inlineStyle = stylePairs.join(';')
      itemSibling.setAttribute('style', inlineStyle)
    }
  }
  getBorderConfig(config, isDetailTable) {
    if (config && config.borderWidth === '0') {
      return isDetailTable ? '1px solid #ebeef5' : '0px'
    }
    if (!config || !config.borderType || !config.borderColor) {
      return isDetailTable ? '1px solid #ebeef5' : ''
    }
    return `${config.borderWidth}px ${config.borderType} ${config.borderColor}`
  }
}
